<?PHP

class vt
{
    const DIR_UP = 'A';
    const DIR_DOWN = 'B';
    const DIR_LEFT = 'D';
    const DIR_RIGHT = 'C';

    const CUR_SAVE = 's';
    const CUR_LOAD = 'u';
    const CUR_HIDE = '?25l';
    const CUR_SHOW = '?25h';

    const COLOR_NONE = 10;
    const COLOR_BLACK = 30;
    const COLOR_RED = 31;
    const COLOR_GREEN = 32;
    const COLOR_YELLOW = 33;
    const COLOR_BLUE = 34;
    const COLOR_PURPLE = 35;
    const COLOR_WATHET = 36;
    const COLOR_WHITE = 37;

    const CLEAN_SCREEN = "2J";
    const CLEAN_LINEALL = "2K";
    const CLEAN_LINE = "K";

    static public function gotoxy(int $r = 1, int $c = 1, $return_val = FALSE)
    {
        $s = sprintf("\033[%d;%dH", $r, $c);
        if ($return_val)
            return $s;
        echo $s;
    }

    static public function move(int $step = 1, $dir = vt::DIR_DOWN, $return_val = FALSE)
    {
        $s = sprintf("\033[%d%s", $step, $dir);
        if ($return_val)
            return $s;
        echo $s;
    }

    static public function cursor($op = vt::CUR_HIDE, $return_val = FALSE)
    {
        $s = sprintf("\033[%s", $op);
        if ($return_val)
            return $s;
        echo $s;
    }

    static public function output($content, $blod = FALSE, $fcolor = vt::COLOR_NONE, $bcolor = vt::COLOR_NONE, $return_val = FALSE)
    {
        $s = sprintf("\033[%d;%d;%dm$content\033[0m", $blod, $fcolor, $bcolor + 10);
        if ($return_val)
            return $s;
        echo $s;
    }

    static public function clean($op = vt::CLEAN_SCREEN, $return_val = FALSE)
    {
        $s = sprintf("\033[%s", $op);
        if ($return_val)
            return $s;
        echo $s;
    }

    static public function init()
    {
        self::clean();
        self::gotoxy();
    }

    static public function bs()
    {
        self::move(1, vt::DIR_LEFT);
        printf(" ");
        self::move(1, vt::DIR_LEFT);
    }

    static public function cl($line = 1, $row = 1, $col = 1)
    {
        self::gotoxy($row, $col);
        for ($i = 0; $i < $line; ++$i) {
            self::clean(vt::CLEAN_LINEALL);
            self::move();
        }
        for ($i = 0; $i < $line; ++$i) {
            self::move(1, vt::DIR_UP);
        }
    }

    static public function debug($content, $row, $col = 1)
    {
        self::gotoxy($row, $col);
        self::clean(vt::CLEAN_LINEALL);
        printf($content);
        self::cursor(vt::CUR_LOAD);
    }
}

